package cn.jathlon.bigdata;

import gnu.trove.iterator.TLongIntIterator;
import gnu.trove.map.hash.TLongIntHashMap;

/**
 * 稀疏矩阵——空间和时间的折中
 * 矩阵元素值为double型
 * @author chen
 *
 */
public class SparseIntMatrix extends AbstractSparseMatrix{
	
    private final int shift_row;  ///位移数
    private final int mask;  ////掩码
    private TLongIntHashMap valueMap;  ////高效原生类型map
    
    public SparseIntMatrix(int numRows, int numColumn) {
        this.shift_row = minExponent(numColumn);
        this.mask = (1 << shift_row) - 1;
        valueMap = new TLongIntHashMap();
    }

    /**
     * set value.
     * @param row
     * @param col
     * @param value
     */
    public void setValue(int row, int col, int value){
    	valueMap.put(((long)row << shift_row) | col, value);
    }
    
    /**
     * Increments the primitive value mapped to key by 1.
     * @param row
     * @param col
     * @param value
     */
    public void increment(int row, int col){
    	valueMap.increment(((long)row << shift_row) | col);
    }
    
    /**
     * Adjusts the primitive value mapped to the key if the key is present in the map.
     * @param key
     * @param adjust_amount
     * @param put_amount
     */
    public void adjustOrPutValue(int row, int col, int adjust_amount, int put_amount) {
    	valueMap.adjustOrPutValue(((long)row << shift_row) | col, adjust_amount, put_amount);
    }

    /**
     *  Adjusts the primitive value mapped to key.
     * @param key
     * @param amount
     */
    public void adjustValue(int row, int col, int amount) {
    	valueMap.adjustValue(((long)row << shift_row) | col, amount);
    }
    
    /**
     * get value. 0 if not exist.
     * @param row
     * @param col
     * @return
     */
    public double getValue(int row, int col){
    	return valueMap.get(((long)row << shift_row) | col);
    }
    
    /**
     * iterator
     * @return
     */
	public TLongIntIterator iterator(){
		return valueMap.iterator();
	};

	/**
	 * Returns the keys of the map as an array of Coordinate values.
	 * @return
	 */
	public Coordinate[] coordinates(){
		long [] keys = valueMap.keys();
		Coordinate [] allCoordinates = new Coordinate[keys.length];
		for (int i = 0; i < allCoordinates.length; i++) {
			long key = keys[i];
			int col = (int)(key & mask);   ////还原
			int row = (int)(key >> shift_row) & mask;
			allCoordinates[i] = new Coordinate(row, col);
		}
		return allCoordinates;
	}
	
}
